#!/usr/bin/env python3
# -*- coding:utf-8 -*-

# 产生异常
"""
def foo():
    print('before')
    def bar():
        print(1/0) # 除零异常
    
    bar()
    print('after')
foo()

def bar():
    print('before')
    raise Exception('my exception')
    print('after')

bar()
"""

### BaseException及子类
"""
import sys
print('before')
sys.exit(1)
print('SysExit')
print('outer')  # 是否执行?
"""

# 捕获这个异常
"""
import sys
try:
    sys.exit(1)
except SystemExit:
    print('SysExit')
print('outer') # 是否执行?
"""

# KeyboardInterrupt对应的捕获用户中断行为ctrl+c
"""
try:
    import time
    while True:
        time.sleep(0.5)
        pass
except KeyboardInterrupt:
    print('ctrl + c')
print('outer')
"""

#### 自定义异常
"""
class MyException(Exception):
    pass

try:
    raise MyException()
except MyException:  # 捕获自定义异常
    print('catch the exception')
"""

### 异常的捕获
"""
class MyException(Exception):
    pass

try:
    a = 1/0
    raise MyException()  # 自定义
    open('a1.txt')
except MyException:
    print('catch the MyException')
except ZeroDivisionError:
    print('1/0')
except Exception: # 调整except的顺序
    print('Exception')
"""


### as子句
"""
class MyException(Exception):
    def __init__(self,code,message):
        self.code = code
        self.message = message

try:
    raise MyException
except MyException as e:
    print('MyException = {}{}'.format(e.code,e.message))
except Exception as e:
    print('Exception = {}'.format(e))
"""

# raise后跟类名是无参构造实例,因此需要2个参数.
"""
class MyException(Exception):
    def __init__(self,code,message):
        self.code = code
        self.message = message

try:
    raise MyException(200,'ok')
except MyException as e:
    print('MyException = {} {}'.format(e.code,e.message))
except Exception as e:
    print('Exception = {}'.format(e))
"""

### finally子句
"""
try:
    f = open('test.txt')
except FileNotFoundError as e:
    print('{} {} {}'.format(e.__class__,e.errno,e.strerror))
finally:
    print('清理工作')
    f.close()
# 注意f的作用域,解决的办法是在外部定义f.
"""

### 异常的传递
# 线程中测试异常
"""
import threading,time

def foo1():
    return 1/0

def foo2():
    time.sleep(3) # 3秒后抛出异常
    print('foo2 start')
    foo1()
    print('foo2 stop')

t = threading.Thread(target=foo2)
t.start()

while True:
    time.sleep(1)
    print('Everything OK')
    if t.is_alive():
        print('alive')
    else:
        print('dead')
"""


### try嵌套
"""
try:
    try:
        ret = 1 / 0
    except KeyError as e:
        print(e)
    else:
        print('inner OK')
    finally:
        print('inner fin')
except:
    print('outer catch')
finally:
    print('outer fin')
"""
'''
内部捕获不到异常,会向外层传递异常.
但是如果内层有finally且其中有return,break语句,则异常就不会继续向外抛出.
'''

### else子句
try:
    ret = 1 * 0
except ArithmeticError as e:
    print(e)
else:
    print('OK')
finally:
    print('fin')

